package com.wuage.application.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.wuage.application.IUacPermissionService;
import com.wuage.application.IUacRolePermissionService;
import com.wuage.application.IUacRoleService;
import com.wuage.application.IUacTenantService;
import com.wuage.domain.mapper.UacPermissionMapper;
import com.wuage.domain.model.UacPermission;
import com.wuage.domain.model.UacRole;
import com.wuage.domain.model.UacRolePermission;
import com.wuage.domain.model.UacTenant;
import com.wuage.infrastructure.status.PermissionTypeEnum;
import com.wuage.infrastructure.utils.BeanUtils;
import com.wuage.infrastructure.utils.JwtUtils;
import com.wuage.interfaces.permission.domain.CreateOrUpdatePermissionDO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Shynin
 * @version 1.0
 * @date 2020-09-06 23:30
 */
@Service
public class UacPermissionServiceImpl extends ServiceImpl<UacPermissionMapper, UacPermission> implements IUacPermissionService {

    private final static List<UacPermission> systemUacPermission;

    @Resource
    private IUacTenantService uacTenantService;

    @Resource
    private UacPermissionMapper uacPermissionMapper;

    @Resource
    private IUacRolePermissionService uacRolePermissionService;

    @Resource
    private IUacRoleService uacRoleService;

    @Override
    public List<UacPermission> getPermissionByRole(String role) {
        //查询角色
        UacRole uacRole = uacRoleService.getByRoleAndTenant(role, JwtUtils.getLoginUser().getTenantId());
        //查询角色所拥有的权限
        List<UacRolePermission> uacRolePermissions = uacRolePermissionService.selectPermission(uacRole.getId());
        if (CollectionUtils.isEmpty(uacRolePermissions)) {
            return Lists.newArrayList();
        }
        List<UacPermission> uacPermissions =
                this.lambdaQuery()
                        .in(UacPermission::getId, uacRolePermissions.stream().map(UacRolePermission::getMenuId).collect(Collectors.toSet()))
                        .list();
        //进行树状结构处理
        return handleUacPermissionTree(Lists.newArrayList(), uacPermissions);
    }

    @Override
    public List<UacPermission> select(Long parentId) {
        return this.lambdaQuery()
                .eq(UacPermission::getParentId, parentId)
                .eq(UacPermission::getTenantId, JwtUtils.getLoginUser().getTenantId()).list();
    }

    @Override
    public List<UacPermission> getPermissionByRoleWithoutChildren(String role) {

        //查询角色
        UacRole uacRole = uacRoleService.getByRoleAndTenant(role, JwtUtils.getLoginUser().getTenantId());
        //查询角色所拥有的权限
        List<UacRolePermission> uacRolePermissions = uacRolePermissionService.selectPermission(uacRole.getId());
        if (CollectionUtils.isEmpty(uacRolePermissions)) {
            return Lists.newArrayList();
        }
        List<UacPermission> uacPermissions =
                this.lambdaQuery()
                        .in(UacPermission::getId, uacRolePermissions.stream().map(UacRolePermission::getMenuId).collect(Collectors.toSet()))
                        .list();
        //进行树状结构处理
        return uacPermissions;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<UacPermission> createAdminPermission(UacRole uacRole) {
        List<UacPermission> uacPermissions = Lists.newArrayList();
        for (UacPermission uacPermission : systemUacPermission) {
            // 保存菜单/权限信息
            UacPermission uacPermissionPO = BeanUtils.copyProperties(uacPermission, UacPermission.class);
            uacPermissionPO.setTenantId(uacRole.getTenantId());
            uacPermissionPO.setTenantName(uacRole.getTenantName());
            this.save(uacPermissionPO);
            uacPermissions.add(uacPermissionPO);

            // 角色信息和菜单/权限关联
            UacRolePermission uacRolePermission =
                    UacRolePermission.builder()
                            .roleId(uacRole.getId())
                            .menuId(uacPermissionPO.getId())
                            .build();
            uacRolePermissionService.save(uacRolePermission);
        }
        return uacPermissions;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UacPermission createOrUpdate(CreateOrUpdatePermissionDO createOrUpdatePermissionDO) {
        // 查询租户信息
        UacTenant tenant = uacTenantService.getById(JwtUtils.getLoginUser().getTenantId());

        // 创建权限
        UacPermission uacPermission = BeanUtils.copyProperties(createOrUpdatePermissionDO, UacPermission.class);
        uacPermission.setTenantId(tenant.getId());
        uacPermission.setTenantName(tenant.getName());
        this.saveOrUpdate(uacPermission);
        return uacPermission;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(Long id) {
        this.removeById(id);
        List<UacPermission> children = this.lambdaQuery().eq(UacPermission::getParentId, id).eq(UacPermission::getTenantId, JwtUtils.getLoginUser().getTenantId()).list();
        for (UacPermission uacPermission : children) {
            delete(uacPermission.getId());
        }
        return true;
    }

    private List<UacPermission> handleUacPermissionTree(List<UacPermission> parentPermission, List<UacPermission> allPermission) {
        if (CollectionUtils.isEmpty(allPermission)) {
            return Lists.newArrayList();
        }
        if (CollectionUtils.isEmpty(parentPermission)) {
            parentPermission = allPermission.stream().filter(item -> Objects.isNull(item.getParentId()) || item.getParentId() == 0L).collect(Collectors.toList());
        }
        for (UacPermission uacPermission : parentPermission) {
            List<UacPermission> childPermission = allPermission.stream().filter(item -> item.getParentId().equals(uacPermission.getId())).collect(Collectors.toList());
            uacPermission.setChildPermission(childPermission);
            if (CollectionUtil.isNotEmpty(childPermission)) {
                handleUacPermissionTree(childPermission, allPermission);
            }
        }
        return parentPermission;
    }


    static {
        systemUacPermission = Lists.newArrayList();
        UacPermission uacPermission =
                UacPermission.builder()
                        .type(PermissionTypeEnum.MENU.getType())
                        .level(1)
                        .menuName("用户管理")
                        .description("用户管理")
                        .parentId(0L)
                        .frontUrl("/")
                        .build();
        systemUacPermission.add(uacPermission);
        uacPermission =
                UacPermission.builder()
                        .type(PermissionTypeEnum.MENU.getType())
                        .level(1)
                        .menuName("菜单管理")
                        .description("菜单管理")
                        .parentId(0L)
                        .frontUrl("/")
                        .build();
        systemUacPermission.add(uacPermission);
        uacPermission =
                UacPermission.builder()
                        .type(PermissionTypeEnum.MENU.getType())
                        .level(1)
                        .menuName("角色管理")
                        .description("角色管理")
                        .parentId(0L)
                        .frontUrl("/")
                        .build();
        systemUacPermission.add(uacPermission);
        uacPermission =
                UacPermission.builder()
                        .type(PermissionTypeEnum.MENU.getType())
                        .level(1)
                        .menuName("角色权限")
                        .description("角色权限")
                        .parentId(0L)
                        .frontUrl("/")
                        .build();
        systemUacPermission.add(uacPermission);
        uacPermission =
                UacPermission.builder()
                        .type(PermissionTypeEnum.MENU.getType())
                        .level(1)
                        .menuName("字典表管理")
                        .description("字典表管理")
                        .parentId(0L)
                        .frontUrl("/")
                        .build();
        systemUacPermission.add(uacPermission);
    }
}
